package com.luxk.dbt;

import java.io.PrintStream;

public class ExecBlockPerformanceTest extends ExecBlock {
	
	public ExecBlockPerformanceTest(String name, ExecIF parent,
			MainContext mCtx) {
		super(name, parent, mCtx);
		this.name = name;
		this.parent = parent;
		this.mCtx = mCtx;
		
		this.result = new Result(this, name);
	}

	@Override
	public void addChild(ExecIF child) throws DBTException {
		
		if(!(child instanceof ExecBlockThread) &&
				!(child instanceof ExecBlockThreads))
			throw new DBTException(
				child.getClass().getName() +
				" is unsupported class to add child " +
						this.getClass().getName(), this.line);
		
		this.children.add(child);
		this.result.addChild(child.getResult());
	}

	@Override
	public void prepareInternal() throws DBTException, DataException {
		
		if(!this.mCtx.isRunMain())
			return;

		int cnt = 0;
		for(ExecIF e: this.children) {
			if(e instanceof ExecBlockThreads) {
				if(++cnt > 1)
					throw new DBTException(e.getClass().getName() +
							" tow or more defs");
				((ExecBlockThreads)e).setCount(this.mCtx.getThreadCount());
				((ExecBlockThreads)e).setDuration(this.mCtx.getDuration());
			}
			if(e instanceof ExecBlockThread) {
				((ExecBlockThread)e).setDuration(this.mCtx.getDuration());
			}
		}
	}
	
	@Override
	public ExecIF duplicate(ExecIF parent) throws DBTException {
		throw new DBTException(
				this.getClass().getName() + " unsupport duplicate",
				this.line);
	}

	@Override
	public void runInternal() throws DBTException {
		
		if(!this.mCtx.isRunMain())
			return;

		long interval = this.mCtx.getCheckInterval() * 1000; // ms
		long startTime = System.currentTimeMillis();
		long checkTime = startTime;
		Display rep = this.mCtx.getReporter();
		PrintStream out = this.mCtx.getWriteStream();
		int printCnt = 0;
		
		this.result.begin();
		rep.setStartTime();
		
		for(ExecIF e: this.children)
			e.run();
		
		if(interval > 0)
			rep.printPartialHeader(out);
		
		do {
			// wait for 1 sec
			synchronized(this) {
				try {
					wait(1 * 1000);
				} catch(InterruptedException e) {}
			}
			
			// check and gather statistics periodically
			if(interval > 0 &&
					System.currentTimeMillis() - checkTime > interval) {
				checkTime = System.currentTimeMillis();
				if(++printCnt % 40 == 0)
					rep.printPartialPage(out);
				rep.printPartialResult(this.result, out);
			}

		} while(!isFinished());

		this.result.setSuccess();
		
		if(interval > 0)
			rep.printPartialTail(out);
		
		// gather result
		rep.printOverallResult(this.result, out);
	}
	
	@Override
	public void cleanupInternal() throws DBTException {}
	
	private boolean isFinished() {
		boolean finished = true;
		
		for(ExecIF e: this.children) {
			if(e instanceof ExecBlockThreads &&
					!((ExecBlockThreads)e).isFinished()) {
				finished = false;
			}
			if(e instanceof ExecBlockThread &&
					!((ExecBlockThread)e).isFinished()) {
				finished = false;
			}
		}
		
		return finished;
	}

	@Override
	public SessionContext getSessionContext() throws DBTException {
		throw new DBTException(
				this.getClass().getName() + " unsupport getSessionContext",
				this.line);
	}

}
